home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / send.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  27KB  |  1,189 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20. #include "mutt_curses.h"
  21. #include "keymap.h"
  22. #include "send.h"
  23. #include "mime.h"
  24. #include "mailbox.h"
  25. #include "copy.h"
  26. #include "state.h"
  27. #include "parse.h"
  28. #include "mx.h"
  29.  
  30. #include <ctype.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <string.h>
  34. #include <errno.h>
  35. #include <sys/stat.h>
  36. #include <sys/wait.h>
  37. #include <dirent.h>
  38.  
  39.  
  40.  
  41. #ifdef _PGPPATH
  42. #include "pgp.h"
  43. #endif
  44.  
  45.  
  46.  
  47. FILE *mutt_open_read (const char *path, pid_t *thepid)
  48. {
  49.   FILE *f;
  50.   int len = strlen (path);
  51.  
  52.   if (path[len-1] == '|')
  53.   {
  54.     /* read from a pipe */
  55.  
  56.     char *s = safe_strdup (path);
  57.  
  58.     s[len-1] = 0;
  59.     endwin ();
  60.     *thepid = mutt_create_filter (s, NULL, &f, NULL);
  61.     free (s);
  62.   }
  63.   else
  64.   {
  65.     f = fopen (path, "r");
  66.     *thepid = -1;
  67.   }
  68.   return (f);
  69. }
  70.  
  71. static void append_signature (ENVELOPE *env, FILE *f)
  72. {
  73.   FILE *tmpfp;
  74.   pid_t thepid;
  75.  
  76.   if ((tmpfp = mutt_open_read (Signature, &thepid)))
  77.   {
  78.     if (option (OPTSIGDASHES))
  79.       fputs ("\n-- \n", f);
  80.     mutt_copy_stream (tmpfp, f);
  81.     fclose (tmpfp);
  82.     if (thepid != -1)
  83.       mutt_wait_filter (thepid);
  84.   }
  85. }
  86.  
  87. /* compare two e-mail addresses and return 1 if they are equivalent */
  88. static int mutt_addrcmp (ADDRESS *a, ADDRESS *b)
  89. {
  90.   if (!a->mailbox || !b->mailbox)
  91.     return 0;
  92.   if (strcasecmp (a->mailbox, b->mailbox))
  93.     return 0;
  94.   if (!a->host || !b->host)
  95.   {
  96.     if (!a->host && !b->host)
  97.       return 1;
  98.     else
  99.       return 0;
  100.   }
  101.   if (strcasecmp (a->host, b->host))
  102.     return 0;
  103.   return 1;
  104. }
  105.  
  106. /* search an e-mail address in a list */
  107. static int mutt_addrsrc (ADDRESS *a, ADDRESS *lst)
  108. {
  109.   for (; lst; lst = lst->next)
  110.   {
  111.     if (mutt_addrcmp (a, lst))
  112.       return (1);
  113.   }
  114.   return (0);
  115. }
  116.  
  117. /* removes addresses from "b" which are contained in "a" */
  118. static ADDRESS *mutt_remove_xrefs (ADDRESS *a, ADDRESS *b)
  119. {
  120.   ADDRESS *top, *p, *prev = NULL;
  121.  
  122.   top = b;
  123.   while (b)
  124.   {
  125.     p = a;
  126.     while (p)
  127.     {
  128.       if (mutt_addrcmp (p, b))
  129.     break;
  130.       p = p->next;
  131.     }
  132.     if (p)
  133.     {
  134.       if (prev)
  135.       {
  136.     prev->next = b->next;
  137.     b->next = NULL;
  138.     mutt_free_address (&b);
  139.     b = prev;
  140.       }
  141.       else
  142.       {
  143.     top = top->next;
  144.     b->next = NULL;
  145.     mutt_free_address (&b);
  146.     b = top;
  147.       }
  148.     }
  149.     else
  150.     {
  151.       prev = b;
  152.       b = b->next;
  153.     }
  154.   }
  155.   return top;
  156. }
  157.  
  158. /* remove any address which matches the current user.  if `leave_only' is
  159.  * nonzero, don't remove the user's address if it is the only one in the list
  160.  */
  161. static ADDRESS *remove_user (ADDRESS *a, int leave_only)
  162. {
  163.   ADDRESS *top = NULL, *last = NULL;
  164.  
  165.   while (a)
  166.   {
  167.     if (!mutt_addr_is_user (a))
  168.     {
  169.       if (top)
  170.       {
  171.         last->next = a;
  172.         last = last->next;
  173.       }
  174.       else
  175.         last = top = a;
  176.       a = a->next;
  177.       last->next = NULL;
  178.     }
  179.     else
  180.     {
  181.       ADDRESS *tmp = a;
  182.       
  183.       a = a->next;
  184.       if (!leave_only || (a && a->next) || last)
  185.       {
  186.     tmp->next = NULL;
  187.     mutt_free_address (&tmp);
  188.       }
  189.     }
  190.   }
  191.   return top;
  192. }
  193.  
  194. static ADDRESS *find_mailing_lists (ADDRESS *t, ADDRESS *c)
  195. {
  196.   ADDRESS *top = NULL, *ptr = NULL, *tmp;
  197.  
  198.   for (; t || c; t = c, c = NULL)
  199.   {
  200.     for (; t; t = t->next)
  201.     {
  202.       if (mutt_is_mail_list (t))
  203.       {
  204.     /* rfc822_cpy_adr() copies the whole list, not just one element, so
  205.      * temporarily cut the list.
  206.      */
  207.     tmp = t->next;
  208.     t->next = NULL;
  209.     if (top)
  210.     {
  211.       ptr->next = rfc822_cpy_adr (t);
  212.       ptr = ptr->next;
  213.     }
  214.     else
  215.       ptr = top = rfc822_cpy_adr (t);
  216.     t->next = tmp; /* restore list */
  217.       }
  218.     }
  219.   }
  220.   return top;
  221. }
  222.  
  223. static int edit_envelope (ENVELOPE *en)
  224. {
  225.   char buf[HUGE_STRING];
  226.  
  227.   buf[0] = 0;
  228.   rfc822_write_address (buf, sizeof (buf), en->to);
  229.   if (mutt_get_field ("To: ", buf, sizeof (buf), M_ALIAS) != 0 || !buf[0])
  230.     return (-1);
  231.   mutt_free_address (&en->to);
  232.   mutt_parse_adrlist (&en->to, buf, "@");
  233.   en->to = mutt_expand_aliases (en->to);
  234.  
  235.   if (option (OPTASKCC))
  236.   {
  237.     buf[0] = 0;
  238.     rfc822_write_address (buf, sizeof (buf), en->cc);
  239.     if (mutt_get_field ("Cc: ", buf, sizeof (buf), M_ALIAS) != 0)
  240.       return (-1);
  241.     mutt_free_address (&en->cc);
  242.     mutt_parse_adrlist (&en->cc, buf, "@");
  243.     en->cc = mutt_expand_aliases (en->cc);
  244.   }
  245.  
  246.   if (option (OPTASKBCC))
  247.   {
  248.     buf[0] = 0;
  249.     rfc822_write_address (buf, sizeof (buf), en->bcc);
  250.     if (mutt_get_field ("Bcc: ", buf, sizeof (buf), M_ALIAS) != 0)
  251.       return (-1);
  252.     mutt_free_address (&en->bcc);
  253.     mutt_parse_adrlist (&en->bcc, buf, "@");
  254.     en->bcc = mutt_expand_aliases (en->bcc);
  255.   }
  256.  
  257.   if (en->subject)
  258.   {
  259.     if (option (OPTFASTREPLY))
  260.       return (0);
  261.     else
  262.       strfcpy (buf, en->subject, sizeof (buf));
  263.   }
  264.   else
  265.     buf[0] = 0;
  266.   if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) != 0 ||
  267.       (!buf[0] && query_quadoption (OPT_SUBJECT, "No subject, abort?") != 0))
  268.     {
  269.       mutt_message ("No subject, aborting.");
  270.       return (-1);
  271.     }
  272.   safe_free ((void **) &en->subject);
  273.   en->subject = safe_strdup (buf);
  274.  
  275.   return 0;
  276. }
  277.  
  278. static void process_user_recips (ENVELOPE *env)
  279. {
  280.   LIST *uh = UserHeader;
  281.  
  282.   for (; uh; uh = uh->next)
  283.   {
  284.     if (strncasecmp ("to:", uh->data, 3) == 0)
  285.       rfc822_parse_adrlist (&env->to, uh->data + 3, "@");
  286.     else if (strncasecmp ("cc:", uh->data, 3) == 0)
  287.       rfc822_parse_adrlist (&env->cc, uh->data + 3, "@");
  288.     else if (strncasecmp ("bcc:", uh->data, 4) == 0)
  289.       rfc822_parse_adrlist (&env->bcc, uh->data + 4, "@");
  290.   }
  291. }
  292.  
  293. static void process_user_header (ENVELOPE *env)
  294. {
  295.   LIST *uh = UserHeader;
  296.   LIST *last = env->userhdrs;
  297.  
  298.   if (last)
  299.     while (last->next)
  300.       last = last->next;
  301.  
  302.   for (; uh; uh = uh->next)
  303.   {
  304.     if (strncasecmp ("from:", uh->data, 5) == 0)
  305.     {
  306.       /* User has specified a default From: address.  Get rid of the
  307.        * default address.
  308.        */
  309.       mutt_free_address (&env->from);
  310.       rfc822_parse_adrlist (&env->from, uh->data + 5, "@");
  311.     }
  312.     else if (strncasecmp ("reply-to:", uh->data, 9) == 0)
  313.     {
  314.       mutt_free_address (&env->reply_to);
  315.       rfc822_parse_adrlist (&env->reply_to, uh->data + 9, "@");
  316.     }
  317.     else if (strncasecmp ("to:", uh->data, 3) != 0 &&
  318.          strncasecmp ("cc:", uh->data, 3) != 0 &&
  319.          strncasecmp ("bcc:", uh->data, 4) != 0)
  320.     {
  321.       if (last)
  322.       {
  323.     last->next = mutt_new_list ();
  324.     last = last->next;
  325.       }
  326.       else
  327.     last = env->userhdrs = mutt_new_list ();
  328.       last->data = safe_strdup (uh->data);
  329.     }
  330.   }
  331. }
  332.  
  333. LIST *mutt_copy_list (LIST *p)
  334. {
  335.   LIST *t, *r=NULL, *l=NULL;
  336.  
  337.   for (; p; p = p->next)
  338.   {
  339.     t = (LIST *) safe_malloc (sizeof (LIST));
  340.     t->data = safe_strdup (p->data);
  341.     t->next = NULL;
  342.     if (l)
  343.     {
  344.       r->next = t;
  345.       r = r->next;
  346.     }
  347.     else
  348.       l = r = t;
  349.   }
  350.   return (l);
  351. }
  352.  
  353. /* include a message as a reply or forward */
  354. static int include_message (HEADER *cur, FILE *out, int forward)
  355. {
  356.   char buffer[STRING];
  357.   int flags = 0;
  358.   
  359.  
  360.  
  361. #ifdef _PGPPATH
  362.   if (cur->pgp)
  363.   {
  364.     if (cur->pgp == PGPENCRYPT)
  365.     {
  366.       /* make sure we have the user's passphrase before proceeding... */
  367.       pgp_valid_passphrase ();
  368.     }
  369.   }
  370. #endif /* _PGPPATH */
  371.  
  372.  
  373.  
  374.   if (forward)
  375.   {
  376.     fputs ("----- Forwarded message from ", out);
  377.     buffer[0] = 0;
  378.     rfc822_write_address (buffer, sizeof (buffer), cur->env->from);
  379.     fputs (buffer, out);
  380.     fputs (" -----\n", out);
  381.   }
  382.   else if (Attribution[0])
  383.   {
  384.     mutt_make_string (buffer, sizeof (buffer), Attribution, cur);
  385.     fputs (buffer, out);
  386.     fputc ('\n', out);
  387.